﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DTD2013.DTDComponent;
using DevExpress.XtraEditors;
using DTD2013.Common;
using DTD2013.Entities;
using DevExpress.XtraTreeList;
using System.Threading;
using DTD2013.DTDLib;
using DTD2013.MainApp.UI;
using DevExpress.XtraEditors.Controls;
using System.Text.RegularExpressions;
using DevExpress.XtraTreeList.Nodes;
using DevExpress.Utils.Drawing;
using DevExpress.XtraGrid.Views.Grid;
using System.Xml.Linq;
using System.Collections;

namespace DTD2013.MainApp
{
    public partial class Deluxe : XtraForm
    {
        #region Properties

        /// <summary>
        /// Gets or sets the link of file static text status
        /// </summary>
        public string FilePath
        {
            get { return bsiLinkFile.Caption; }
            set { bsiLinkFile.Caption = value; }
        }

        /// <summary>
        /// Gets or sets the status of file static text status (saved, open, editing)
        /// </summary>
        public string StatusFile
        {
            get { return bsiStatusFile.Caption; }
            set { bsiStatusFile.Caption = value; }
        }

        /// <summary>
        /// Gets or sets status of file are saved or not
        /// </summary>
        public bool FileSaved { get; set; }

        /// <summary>
        /// Gets or sets cancel status of form
        /// </summary>
        public bool IsCancel { get; set; }

        /// <summary>
        /// Gets or sets status of data norm is edited or not
        /// </summary>
        public bool IsEditNorm { get; set; }

        /// <summary>
        /// Gets or sets auto calculate update kl
        /// </summary>
        public bool AutoCalculateKL { get; set; }

        #endregion

        #region Variable

        /// <summary>
        /// "CongTac" list that binding to trlCongViec treelist control
        /// </summary>
        private BindingList<CongTac> CongTacList;

        /// <summary>
        /// Thanh tien luc vua mo nhap lieu
        /// </summary>
        private Dictionary<string, double> ThanhTienGoc;

        /// <summary>
        /// Luu tru cac cong viec tam tinh
        /// </summary>
        private List<CongTac> CongTacTamTinhList;

        /// <summary>
        /// Tong hop cac hao phi tu CongTacList
        /// </summary>
        private BindingList<DinhMuc> TongHopHaoPhiList;

        /// <summary>
        /// Danh sach tong hop chi phi xay dung
        /// </summary>
        private BindingList<ChiPhiXayDung> ChiPhiXayDungList;

        /// <summary>
        /// Data context entities
        /// </summary>
        private DeluxeEntities DeluxeContext;

        /// <summary>
        /// List of excluded properties when copy object to another
        /// </summary>
        private string[] ExcludedProperties = new string[] { "ID", "ParentID", "STT" };

        /// <summary>
        /// Selected province
        /// </summary>
        private string Province = string.Empty;

        /// <summary>
        /// The old work code
        /// </summary>
        private string OldWorkCode = string.Empty;

        /// <summary>
        /// Trigger when user focus new row
        /// </summary>
        private bool FocusedNewRow = false;

        /// <summary>
        /// Thanh tien vat lieu tam tinh
        /// </summary>
        private double AgentPrice = 0;
        /// <summary>
        /// Thanh tien nhan cong tam tinh
        /// </summary>
        private double PeoplePrice = 0;
        /// <summary>
        /// Thanh tien ca may tam tinh
        /// </summary>
        private double MachinePrice = 0;
        /// <summary>
        /// He so day du
        /// </summary>
        private double HSDD = 0;

        /// <summary>
        /// Copy chi phi xay dung
        /// </summary>
        private ChiPhiXayDung ChiPhiXayDungCopy = null;

        /// <summary>
        /// He so vat lieu
        /// </summary>
        private double HSVL = 1;
        /// <summary>
        /// He so nhan cong
        /// </summary>
        private double HSNC = 1;
        /// <summary>
        /// He so ca may
        /// </summary>
        private double HSCM = 1;

        /// <summary>
        /// Ten hao phi
        /// </summary>
        private string TenVatLieu = string.Empty;

        /// <summary>
        /// Auto increase number
        /// </summary>
        private int AutoIncrease = 0;

        /// <summary>
        /// Tracking undo congtac
        /// </summary>
        private DTDStack<TrackingObject<CongTac>> UndoCT = new DTDStack<TrackingObject<CongTac>>();

        /// <summary>
        /// Tracking redo congtac
        /// </summary>
        private DTDStack<TrackingObject<CongTac>> RedoCT = new DTDStack<TrackingObject<CongTac>>();

        #endregion

        #region Constructor

        public Deluxe()
        {
            InitializeComponent();

            Initialize();

            InitializeTab1();
            InitializeTab2();
            InitializeTab3();
            InitializeTab4();
        }

        private void Deluxe_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!FileSaved)
            {
                DialogResult saveDlg = XtraMessageBox.Show(string.Format(MessageResource.CONFIRM_SAVE_BEFORE_CLOSE, this.Text),
                                                           MessageResource.WARNING,
                                                           MessageBoxButtons.YesNoCancel,
                                                           MessageBoxIcon.Warning);
                if (saveDlg == DialogResult.Yes)
                {
                    Startup start = this.ParentForm as Startup;
                    start.SaveCurrentDeluxe();
                    if (string.IsNullOrEmpty(FilePath))
                    {
                        e.Cancel = true;
                        IsCancel = true;
                    }
                    else
                    {
                        IsCancel = false;
                        if (start.MdiChildren.Count() == 0)
                        {
                            start.SetFocusRibbonPage(SelectedRibbonPage.HeThong);
                        }
                    }
                }
                else if (saveDlg == DialogResult.Cancel)
                {
                    e.Cancel = true;
                    IsCancel = true;
                }
                else
                {
                    IsCancel = false;
                    Startup start = this.ParentForm as Startup;
                    if (start.MdiChildren.Count() == 1)
                    {
                        start.SetFocusRibbonPage(SelectedRibbonPage.HeThong);
                    }
                }
            }
        }

        private void xtraTabMain_SelectedPageChanged(object sender, DevExpress.XtraTab.TabPageChangedEventArgs e)
        {
            if (e.Page.Name.Equals(Constant.TAB3_NAME))
            {
                UpdateTongHopHaoPhiList();
            }
        }

        #endregion

        #region Private method

        #region Init constructor

        private void Initialize()
        {
            dgcHaoPhi.InitializeControl();
            dgcTHCPXD.InitializeControl();

            FileSaved = true;
            IsEditNorm = false;
            IsCancel = false;
            AutoCalculateKL = false;

            CongTacList = new BindingList<CongTac>();
            CongTacTamTinhList = new List<CongTac>();
            ChiPhiXayDungList = new BindingList<ChiPhiXayDung>();
            TongHopHaoPhiList = new BindingList<DinhMuc>();
            ThanhTienGoc = new Dictionary<string, double>();

            DeluxeContext = new DeluxeEntities();
        }

        /// <summary>
        /// Update dtd total price on status bar
        /// </summary>
        private void UpdatePriceStatus()
        {
            beiTxtTotalPrice.EditValue = CalculateTotalPrice();
            beiTxtAgentPrice.EditValue = ChiPhiXayDungList.Where(c => c.KyHieu.Equals(Constant.CPVL)).First().ThanhTien;
            beiTxtPeoplePrice.EditValue = ChiPhiXayDungList.Where(c => c.KyHieu.Equals(Constant.CPNC)).First().ThanhTien;
            beiTxtMachinePrice.EditValue = ChiPhiXayDungList.Where(c => c.KyHieu.Equals(Constant.CPCM)).First().ThanhTien;
        }

        #endregion

        #region Tab1

        private void InitializeTab1()
        {
            dteNgayLap.DateTime = DateTime.Now;
            dteNgaySua.DateTime = DateTime.Now;

            // Lookup edit loai hinh chinh
            List<Config> configList = DeluxeContext.Configs.ToList();
            List<Config> loaiHinhChinhs = configList.Where(c => c.ConfigGroup
                                                    .Equals(ConfigGroup.LoaiHinhChinh.ToString(),
                                                            StringComparison.OrdinalIgnoreCase)).ToList();
            lkeLoaiCongTrinh.Properties.DataSource = loaiHinhChinhs;
            lkeLoaiCongTrinh.EditValue = Constant.DEFAULT_MAIN_TYPE;

            // Lookup edit cap cong trinh
            List<Config> capCongTrinhs = configList.Where(c => c.ConfigGroup
                                                   .Equals(ConfigGroup.CapCongTrinh.ToString(),
                                                           StringComparison.OrdinalIgnoreCase)).ToList();
            lkeCapCongTrinh.Properties.DataSource = capCongTrinhs;
            lkeCapCongTrinh.EditValue = Constant.DEFAULT_BuildingLevel;

            // Lookup edit so buoc thiet ke
            List<Config> soBuocThietKes = configList.Where(c => c.ConfigGroup
                                                   .Equals(ConfigGroup.SoBuocThietKe.ToString(),
                                                           StringComparison.OrdinalIgnoreCase)).ToList();
            lkeSoBuocThietKe.Properties.DataSource = soBuocThietKes;
            lkeSoBuocThietKe.EditValue = Constant.DEFAULT_DESIGN_STEP;

            // Lookup edit Phuong phap tinh
            List<Config> phuongPhapTinhs = configList.Where(c => c.ConfigGroup
                                                   .Equals(ConfigGroup.PhuongThucTinh.ToString(),
                                                           StringComparison.OrdinalIgnoreCase)).ToList();
            lkePhuongPhapTinh.Properties.DataSource = phuongPhapTinhs;
            lkePhuongPhapTinh.EditValue = Constant.DEFAULT_NORM;

            // Lookup edit du toan hay tham tra
            List<Config> duToanThamTras = configList.Where(c => c.ConfigGroup
                                                   .Equals(ConfigGroup.DuToanThamTra.ToString(),
                                                           StringComparison.OrdinalIgnoreCase)).ToList();
            lkeDuToanThamTra.Properties.DataSource = duToanThamTras;
            lkeDuToanThamTra.EditValue = Constant.DEFAULT_ESTIMATE;

            // Lookup edit thuoc tinh
            List<TinhThanh> tinhThanhs = DeluxeContext.TinhThanhs.ToList();
            lkeThuocTinh.Properties.DataSource = tinhThanhs;
            lkeThuocTinh.EditValue = Constant.DEFAULT_PROVINCE;
            Province = lkeThuocTinh.EditValue.ToString();

            // Event handler
            lkeThuocTinh.EditValueChanged += new EventHandler(lkeThuocTinh_EditValueChanged);
            lkePhuongPhapTinh.EditValueChanged += new EventHandler(lkePhuongPhapTinh_EditValueChanged);
        }

        private void bteTenDuAn_ButtonClick(object sender, ButtonPressedEventArgs e)
        {
            OpenFileDialog openDlg = new OpenFileDialog();
            openDlg.Filter = Constant.XML_FILTER;
            openDlg.InitialDirectory = Application.ExecutablePath;
            openDlg.Title = Constant.OPEN_FILE_DIALOG_TITLE;
            if (openDlg.ShowDialog() == DialogResult.OK)
            {
                XDocument doc = XDocument.Load(openDlg.FileName);
                if (doc == null)
                {
                    ((Startup)this.ParentForm).ShowErrorMessage(MessageResource.LOAD_ERROR);
                    return;
                }

                #region Tab1

                ThongTinDT ttDT = DataUtilities.LoadTab1(doc);
                bteTenDuAn.EditValue = ttDT.TenDuAn;
                txtTenCongTrinh.Text = ttDT.TenCongTrinh;
                txtDiaDiemCongTrinh.Text = ttDT.DiaDiemCongTrinh;
                txtTenChuDauTu.Text = ttDT.TenChuDauTu;
                txtTenNhaThau.Text = ttDT.TenNhaThau;
                txtTenChuTri.Text = ttDT.TenChuTriLapDauTu;
                txtKSDG.Text = ttDT.KSDG;
                txtHang.Text = ttDT.Hang;
                lkeLoaiCongTrinh.EditValue = ttDT.LoaiHinhChinh;
                lkeCapCongTrinh.EditValue = ttDT.CapCongTrinh;
                lkeSoBuocThietKe.EditValue = ttDT.SoBuocThietKe;
                lkePhuongPhapTinh.EditValue = ttDT.PhuongPhapTinh;
                lkeThuocTinh.EditValue = ttDT.ThuocTinh;
                lkeDuToanThamTra.EditValue = ttDT.DuToanHayThamTra;
                dteNgayLap.DateTime = ttDT.NgayLap;
                dteNgaySua.DateTime = ttDT.NgaySua;
                //txtMatKhau.Text = ttDT.MatKhau;
                chkHoTroNhap.Checked = ttDT.HoTroNhap;

                #endregion
            }
        }

        private void lkeThuocTinh_EditValueChanged(object sender, EventArgs e)
        {
            Province = lkeThuocTinh.EditValue.ToString();

            string sourceTable = lkeThuocTinh.OldEditValue != null ?
                string.Format(Constant.TDVT, lkeThuocTinh.OldEditValue.ToString()) : Constant.TPHCM_TDVT;
            string desTable = string.Format(Constant.TDVT, Province);
            DataUtilities.GenerateDataFromStandardData(sourceTable, desTable);

            // Reset price
            AgentPrice = 0;
            PeoplePrice = 0;
            MachinePrice = 0;
            foreach (CongTac ct in CongTacList)
            {
                ct.HaoPhiCongViecs = DataUtilities.GetWasteListByWork(ct, Province, lkePhuongPhapTinh.EditValue.ToString());
                AgentPrice += ct.TTVL;
                PeoplePrice += ct.TTNC;
                MachinePrice += ct.TTCM;
            }
            // Update price status
            UpdatePriceStatus();
        }

        private void lkePhuongPhapTinh_EditValueChanged(object sender, EventArgs e)
        {
            UpdateWorkInfoPrice(lkePhuongPhapTinh.EditValue.ToString());
        }

        /// <summary>
        /// Update work price when calculate method changes value
        /// </summary>
        /// <param name="calculateMethod">Calculate method</param>
        private void UpdateWorkInfoPrice(string calculateMethod)
        {
            // Reset price
            AgentPrice = 0;
            PeoplePrice = 0;
            MachinePrice = 0;

            if (calculateMethod.Equals(Constant.DEFAULT_NORM))
            {
                foreach (CongTac cv in CongTacList)
                {
                    cv.DGNC = cv.HaoPhiCongViecs.Where(hp =>
                        hp.LoaiHaoPhi.Equals(WasteType.E.ToString())).Sum(hp => hp.ThanhTien);
                    cv.DGCM = cv.HaoPhiCongViecs.Where(hp =>
                        hp.LoaiHaoPhi.Equals(WasteType.F.ToString())).Sum(hp => hp.ThanhTien);
                    cv.DGVL = cv.HaoPhiCongViecs.Where(hp =>
                        !hp.LoaiHaoPhi.Equals(WasteType.E.ToString()) &&
                        !hp.LoaiHaoPhi.Equals(WasteType.F.ToString())).Sum(hp => hp.ThanhTien);
                    // Cap nhat lai gia vat lieu khac
                    var query = cv.HaoPhiCongViecs.Where(v => v.MaVatLieu.Equals(Constant.VL_KHAC));
                    if (query.Count() > 0)
                    {
                        DinhMuc vlKhac = query.First();
                        cv.DGVL -= vlKhac.ThanhTien;
                        vlKhac.ThanhTien = (cv.DGVL.Value * vlKhac.KhoiLuong) / 100;
                        cv.DGVL += vlKhac.ThanhTien;
                    }
                    // Cap nhat lai gia ca may khac
                    query = cv.HaoPhiCongViecs.Where(v => v.MaVatLieu.Equals(Constant.CM_KHAC));
                    if (query.Count() > 0)
                    {
                        DinhMuc cmKhac = query.First();
                        cv.DGCM -= cmKhac.ThanhTien;
                        cmKhac.ThanhTien = (cv.DGCM.Value * cmKhac.KhoiLuong) / 100;
                        cv.DGCM += cmKhac.ThanhTien;
                    }

                    cv.DGVL *= cv.HSVL;
                    cv.DGNC *= cv.HSNC;
                    cv.DGCM *= cv.HSCM;
                    cv.TTVL = cv.KhoiLuong * cv.DGVL.Value;
                    cv.TTNC = cv.KhoiLuong * cv.DGNC.Value;
                    cv.TTCM = cv.KhoiLuong * cv.DGCM.Value;
                    cv.TongCong = cv.TTVL + cv.TTNC + cv.TTCM;
                    AgentPrice += cv.TTVL;
                    PeoplePrice += cv.TTNC;
                    MachinePrice += cv.TTCM;
                }
            }
            else
            {
                foreach (CongTac cv in CongTacList)
                {
                    var query = DeluxeContext.CongTacs.Where(c => c.MaHieu.Equals(cv.MaHieu));
                    if (query.Count() > 0)
                    {
                        CongTac tmp = query.FirstOrDefault();
                        cv.DGVL = tmp.DGVL;
                        cv.DGNC = tmp.DGNC;
                        cv.DGCM = tmp.DGCM;
                        cv.TTVL = cv.KhoiLuong * cv.DGVL.Value * cv.HSVL;
                        cv.TTNC = cv.KhoiLuong * cv.DGNC.Value * cv.HSNC;
                        cv.TTCM = cv.KhoiLuong * cv.DGCM.Value * cv.HSCM;
                        cv.TongCong = cv.TTVL + cv.TTNC + cv.TTCM;
                        AgentPrice += cv.TTVL;
                        PeoplePrice += cv.TTNC;
                        MachinePrice += cv.TTCM;
                    }
                }
            }
            // Update price
            UpdatePriceStatus();
            // update nhom CV
            IEnumerable<int> nhomIDs = CongTacList.Where(c => c.ParentID == -1).Select(c => c.ID);
            foreach (int id in nhomIDs)
            {
                UpdateNhomCV(id);
            }
        }

        #endregion

        #region Tab2

        private void InitializeTab2()
        {
            trlCongViec.DataSource = CongTacList;
            // Them nhom cong viec dau tien
            CongTac root = new CongTac() { ID = 0, ParentID = -1, MaHieu = Constant.DEFAULT_WORKGROUP };
            CongTacList.Add(root);
            trlCongViec.RefreshDataSource();

            // assign column edit
            dgvHaoPhi.Columns["KhoiLuong"].ColumnEdit = rpiTxtDoubleNumber;
            dgvHaoPhi.Columns["KhoiLuongCan"].ColumnEdit = rpiTxtDoubleNumber;
            dgvHaoPhi.Columns["GiaThuc"].ColumnEdit = rpiTxtIntegerNumber;

            // repository data source
            rpiLkeMacVua.DataSource = DataUtilities.GetMortarList();
            rpiLkeLoaiHP.DataSource = DeluxeContext.LoaiHaoPhis.ToList();


            // event handler
            trlCongViec.CellValueChanged += new CellValueChangedEventHandler(trlCongViec_CellValueChanged);
            trlCongViec.ShowingEditor += new CancelEventHandler(trlCongViec_ShowingEditor);
            trlCongViec.CustomDrawNodeCell += new CustomDrawNodeCellEventHandler(trlCongViec_CustomDrawNodeCell);
            trlCongViec.FocusedNodeChanged += new FocusedNodeChangedEventHandler(trlCongViec_FocusedNodeChanged);
            trlCongViec.KeyUp += new KeyEventHandler(trlCongViec_KeyUp);
            trlCongViec.DragDrop += new DragEventHandler(trlCongViec_DragDrop);
            trlCongViec.DragOver += new DragEventHandler(trlCongViec_DragOver);

            dgvHaoPhi.CellValueChanged += new DevExpress.XtraGrid.Views.Base.CellValueChangedEventHandler(dgvHaoPhi_CellValueChanged);
            dgvHaoPhi.FocusedRowChanged += new DevExpress.XtraGrid.Views.Base.FocusedRowChangedEventHandler(dgvHaoPhi_FocusedRowChanged);
            dgvHaoPhi.KeyUp += new KeyEventHandler(dgvHaoPhi_KeyUp);

            rpiTxtMaHieu.Enter += new EventHandler(rpiTxtMaHieu_Enter);
            rpiTxtMaHieu.Leave += new EventHandler(rpiTxtMaHieu_Leave);

            rpiTxtTenCongViec.Enter += new EventHandler(rpiTxtTenCongViec_Enter);
            rpiTxtTenCongViec.Leave += new EventHandler(rpiTxtTenCongViec_Leave);
            rpiTxtTenCongViec.KeyUp += new KeyEventHandler(rpiTxtTenCongViec_KeyUp);

            rpiTxtIntegerNumber.KeyUp += new KeyEventHandler(rpiTxtIntegerNumber_KeyUp);

            CongTacList.ListChanged += new ListChangedEventHandler(CongTacList_ListChanged);
        }

        private void trlCongViec_DragDrop(object sender, DragEventArgs e)
        {
            UpdateObjectIDAndParentID(trlCongViec.Nodes);
            TreeListNode dragNode, targetNode;
            TreeList tl = sender as TreeList;
            Point p = tl.PointToClient(new Point(e.X, e.Y));

            dragNode = e.Data.GetData(typeof(TreeListNode)) as TreeListNode;
            targetNode = tl.CalcHitInfo(p).Node;

            tl.SetNodeIndex(dragNode, tl.GetNodeIndex(targetNode));
            e.Effect = DragDropEffects.None;

        }

        private DragDropEffects GetDragDropEffect(TreeList tl, TreeListNode dragNode)
        {
            TreeListNode targetNode;
            Point p = tl.PointToClient(MousePosition);
            targetNode = tl.CalcHitInfo(p).Node;

            if (dragNode != null && targetNode != null
                && dragNode != targetNode
                && dragNode.ParentNode == targetNode.ParentNode)
                return DragDropEffects.Move;
            else
                return DragDropEffects.None;
        }

        private void trlCongViec_DragOver(object sender, System.Windows.Forms.DragEventArgs e)
        {
            TreeListNode dragNode = e.Data.GetData(typeof(TreeListNode)) as TreeListNode;
            e.Effect = GetDragDropEffect(sender as TreeList, dragNode);
        }

        private void trlCongViec_CellValueChanged(object sender, CellValueChangedEventArgs e)
        {
            if (string.IsNullOrEmpty(DTDConvert.ConvertToString(e.Value)))
            {
                if (e.Column.FieldName.Equals(CongTacFieldName.TenCongViec.ToString()) &&
                    e.Node.Level == TreeListLevel.ChiTietCV && !FocusedNewRow)
                {
                    CongTac cv = trlCongViec.GetDataRecordByNode(e.Node) as CongTac;
                    if (cv != null)
                    {
                        CongTacList.Remove(cv);
                        //UndoCT.Push(new TrackingObject<CongTac>() { ObjectInfo = cv, Action = TrackingAction.Delete });
                    }
                    UpdateObjectIDAndParentID(trlCongViec.Nodes);
                    return;
                }
                if (e.Column.FieldName.Equals(CongTacFieldName.MaHieu.ToString()) && !FocusedNewRow)
                {
                    CongTac cv = trlCongViec.GetDataRecordByNode(e.Node) as CongTac;
                    if (cv != null)
                    {
                        List<CongTac> childs = CongTacList.Where(c => c.ParentID == e.Node.Id).ToList();
                        foreach (CongTac item in childs)
                        {
                            //List<CongTac> childsOfItem = CongTacList.Where(c => c.ParentID == item.ID).ToList();
                            //foreach (CongTac coi in childsOfItem)
                            //{
                            //    CongTacList.Remove(coi);
                            //    UndoCT.Push(new TrackingObject<CongTac>() { ObjectInfo = coi, Action = TrackingAction.Delete });
                            //}
                            CongTacList.Remove(item);
                            //UndoCT.Push(new TrackingObject<CongTac>() { ObjectInfo = item, Action = TrackingAction.Delete });
                        }
                        CongTacList.Remove(cv);
                        //UndoCT.Push(new TrackingObject<CongTac>() { ObjectInfo = cv, Action = TrackingAction.Delete });
                        UpdateObjectIDAndParentID(trlCongViec.Nodes);

                        OldWorkCode = string.Empty;
                    }
                }
                return;
            }

            FileSaved = false;
            StatusFile = FileStatus.Editing;

            if (e.Column.FieldName.Equals(CongTacFieldName.MaHieu.ToString()))
            {
                if (e.Node.Level == TreeListLevel.NhomCV)
                {
                    #region Nhom cong viec

                    int maxIdNhomCV = CongTacList.Where(c => c.ParentID == -1).Max(c => c.ID);
                    if (e.Node.Id == maxIdNhomCV)
                    {
                        // Them nhom cong viec moi
                        CongTac nhom = new CongTac()
                        {
                            ID = CongTacList.Count,
                            ParentID = -1,
                            MaHieu = Constant.DEFAULT_WORKGROUP
                        };
                        CongTacList.Add(nhom);
                        // Them cong viec cho nhom hien tai neu no chua co cong viec nao
                        if (!e.Node.HasChildren)
                        {
                            CongTac congViec = new CongTac()
                            {
                                ID = CongTacList.Count,
                                ParentID = e.Node.Id,
                                MaHieu = Constant.DEFAULT_WORK,
                                STT = ++AutoIncrease
                            };
                            CongTacList.Add(congViec);
                        }
                    }

                    #endregion
                }
                else if (e.Node.Level == TreeListLevel.CongViec)
                {
                    // Lay cac field va chi tiet hao phi cong viec
                    string maHieu = e.Value.ToString();
                    if (maHieu == OldWorkCode)
                    {
                        return;
                    }

                    #region GTT

                    if (maHieu.StartsWith(Constant.GTT))
                    {
                        // tim cong viec tam tinh luc truoc
                        CongTac cvtt = CongTacTamTinhList.Where(c => c.MaHieu.Equals(maHieu)).FirstOrDefault();
                        if (cvtt == null)
                        {
                            guiWorkTemplate workTemplate = new guiWorkTemplate(CongTacTamTinhList);
                            if (workTemplate.ShowDialog() == DialogResult.OK)
                            {
                                cvtt = new CongTac() { STT = ++AutoIncrease };
                                PropertiesMapper.CopyPropertiesFrom(cvtt, workTemplate.CongTacTamTinh, ExcludedProperties);
                                CongTacTamTinhList.Add(cvtt);
                            }
                            else
                            {
                                e.Node.SetValue(CongTacFieldName.MaHieu.ToString(), Constant.DEFAULT_WORK);
                                return;
                            }
                        }

                        CongTac congViecHienTai = CongTacList.Where(c => c.ID == e.Node.Id).FirstOrDefault();

                        AgentPrice -= congViecHienTai.TTVL;
                        PeoplePrice -= congViecHienTai.TTNC;
                        MachinePrice -= congViecHienTai.TTCM;

                        UpdatePriceStatus();
                        UpdateNhomCV(e.Node.ParentNode.Id);

                        PropertiesMapper.CopyPropertiesFrom(congViecHienTai, cvtt, ExcludedProperties);
                        dgcHaoPhi.DataSource = congViecHienTai.HaoPhiCongViecs;
                        // Them chi tiet cong viec cho cong viec hien tai neu no chua co chi tiet nao
                        if (!e.Node.HasChildren)
                        {
                            CongTac chiTietCV = new CongTac()
                            {
                                ID = CongTacList.Count,
                                ParentID = e.Node.Id,
                                TenCongViec = Constant.DEFAULT_WORK_DETAIL
                            };
                            CongTacList.Add(chiTietCV);
                            // Them cong viec moi vi day la cong viec cuoi cung (do khong co chi tiet)
                            CongTac congViec = new CongTac()
                            {
                                ID = CongTacList.Count,
                                ParentID = e.Node.ParentNode.Id,
                                MaHieu = Constant.DEFAULT_WORK,
                                STT = ++AutoIncrease
                            };
                            CongTacList.Add(congViec);
                        }

                        e.Node.Expanded = true;
                        trlCongViec.FocusedNode = e.Node;
                        trlCongViec.RefreshDataSource();

                        return;
                    }

                    #endregion

                    #region DMM

                    if (maHieu.Equals("DMM"))
                    {
                        guiNormEditor normEditor = new guiNormEditor(Province);
                        if (normEditor.ShowDialog() == DialogResult.OK)
                        {
                            CongTac cvHienTai = CongTacList.Where(c => c.ID == e.Node.Id).First();

                            AgentPrice -= cvHienTai.TTVL;
                            PeoplePrice -= cvHienTai.TTNC;
                            MachinePrice -= cvHienTai.TTCM;

                            UpdatePriceStatus();
                            UpdateNhomCV(e.Node.ParentNode.Id);

                            PropertiesMapper.CopyPropertiesFrom(cvHienTai, normEditor.DinhMucMoi, ExcludedProperties);
                            dgcHaoPhi.DataSource = cvHienTai.HaoPhiCongViecs;
                            // Them chi tiet cong viec cho cong viec hien tai neu no chua co chi tiet nao
                            if (!e.Node.HasChildren)
                            {
                                CongTac chiTietCV = new CongTac()
                                {
                                    ID = CongTacList.Count,
                                    ParentID = e.Node.Id,
                                    TenCongViec = Constant.DEFAULT_WORK_DETAIL
                                };
                                CongTacList.Add(chiTietCV);
                                // Them cong viec moi vi day la cong viec cuoi cung (do khong co chi tiet)
                                CongTac congViec = new CongTac()
                                {
                                    ID = CongTacList.Count,
                                    ParentID = e.Node.ParentNode.Id,
                                    MaHieu = Constant.DEFAULT_WORK,
                                    STT = ++AutoIncrease
                                };
                                CongTacList.Add(congViec);
                            }

                            e.Node.Expanded = true;
                            trlCongViec.FocusedNode = e.Node;
                            trlCongViec.RefreshDataSource();
                        }
                        else
                        {
                            e.Node.SetValue(CongTacFieldName.MaHieu.ToString(), Constant.DEFAULT_WORK);
                            return;
                        }
                        return;
                    }

                    #endregion

                    #region Cong viec

                    CongTac cv = DeluxeContext.CongTacs.Where(c => c.MaHieu.Equals(maHieu,
                                                              StringComparison.OrdinalIgnoreCase))
                                                       .FirstOrDefault();
                    if (cv != null)
                    {
                        #region Update cong viec

                        CongTac congViecHienTai = CongTacList.Where(c => c.ID == e.Node.Id).FirstOrDefault();

                        AgentPrice -= congViecHienTai.TTVL;
                        PeoplePrice -= congViecHienTai.TTNC;
                        MachinePrice -= congViecHienTai.TTCM;

                        UpdatePriceStatus();
                        UpdateNhomCV(e.Node.ParentNode.Id);

                        PropertiesMapper.CopyPropertiesFrom(congViecHienTai, cv, ExcludedProperties);
                        congViecHienTai.HaoPhiCongViecs = DataUtilities.GetWasteListByWork(congViecHienTai,
                                                            Province, lkePhuongPhapTinh.EditValue.ToString());
                        dgcHaoPhi.DataSource = congViecHienTai.HaoPhiCongViecs;
                        // Them chi tiet cong viec cho cong viec hien tai neu no chua co chi tiet nao
                        if (!e.Node.HasChildren)
                        {
                            CongTac chiTietCV = new CongTac()
                            {
                                ID = CongTacList.Count,
                                ParentID = e.Node.Id,
                                TenCongViec = Constant.DEFAULT_WORK_DETAIL
                            };
                            CongTacList.Add(chiTietCV);
                            // Them cong viec moi vi day la cong viec cuoi cung (do khong co chi tiet)
                            CongTac congViec = new CongTac()
                            {
                                ID = CongTacList.Count,
                                ParentID = e.Node.ParentNode.Id,
                                MaHieu = Constant.DEFAULT_WORK,
                                STT = ++AutoIncrease
                            };
                            CongTacList.Add(congViec);
                        }
                        e.Node.Expanded = true;

                        #endregion
                    }
                    else
                    {
                        #region Select list congviec

                        // Show the table of content UI
                        guiTableOfContent tableOfContent = new guiTableOfContent(maHieu, Province, lkePhuongPhapTinh.EditValue.ToString());
                        if (tableOfContent.ShowDialog() == DialogResult.OK)
                        {
                            if (tableOfContent.SelectedList.Count > 0)
                            {
                                // Update first selected work to focused work
                                CongTac cv0 = tableOfContent.SelectedList[0];
                                CongTac congViecHienTai = CongTacList.Where(c => c.ID == e.Node.Id).FirstOrDefault();

                                AgentPrice -= congViecHienTai.TTVL;
                                PeoplePrice -= congViecHienTai.TTNC;
                                MachinePrice -= congViecHienTai.TTCM;

                                UpdatePriceStatus();
                                UpdateNhomCV(e.Node.ParentNode.Id);

                                PropertiesMapper.CopyPropertiesFrom(congViecHienTai, cv0, ExcludedProperties);
                                congViecHienTai.HaoPhiCongViecs = DataUtilities.GetWasteListByWork(congViecHienTai,
                                                                        Province, lkePhuongPhapTinh.EditValue.ToString());
                                // Them chi tiet cong viec cho cong viec hien tai neu no chua co chi tiet nao
                                if (!e.Node.HasChildren)
                                {
                                    CongTac chiTietCV = new CongTac()
                                    {
                                        ID = CongTacList.Count,
                                        ParentID = e.Node.Id,
                                        TenCongViec = Constant.DEFAULT_WORK_DETAIL
                                    };
                                    CongTacList.Add(chiTietCV);
                                }
                                for (int i = 1; i < tableOfContent.SelectedList.Count; i++)
                                {
                                    // Them cong viec
                                    CongTac cvi = tableOfContent.SelectedList[i];
                                    cvi.ID = CongTacList.Count;
                                    cvi.ParentID = e.Node.ParentNode.Id;
                                    cvi.HaoPhiCongViecs = DataUtilities.GetWasteListByWork(cvi, Province,
                                                                            lkePhuongPhapTinh.EditValue.ToString());
                                    dgcHaoPhi.DataSource = cvi.HaoPhiCongViecs;
                                    CongTacList.Add(cvi);
                                    // Them chi tiet cong viec
                                    CongTac chiTietCV = new CongTac()
                                    {
                                        ID = CongTacList.Count,
                                        ParentID = cvi.ID,
                                        TenCongViec = Constant.DEFAULT_WORK_DETAIL
                                    };
                                    CongTacList.Add(chiTietCV);
                                }
                                // Them cong viec moi de tiep tuc nhap lieu
                                CongTac congViec = new CongTac()
                                {
                                    ID = CongTacList.Count,
                                    ParentID = e.Node.ParentNode.Id,
                                    MaHieu = Constant.DEFAULT_WORK,
                                    STT = ++AutoIncrease
                                };
                                CongTacList.Add(congViec);
                            }
                        }

                        #endregion
                    }
                    trlCongViec.FocusedNode = e.Node;

                    #endregion
                }
            }
            else if (e.Column.FieldName.Equals(CongTacFieldName.TenCongViec.ToString()))
            {
                #region Chi tiet cong viec

                if (e.Node.Level == TreeListLevel.ChiTietCV)
                {
                    int parentId = e.Node.ParentNode.Id;
                    int maxIdChiTietCV = CongTacList.Where(c => c.ParentID == parentId).Max(c => c.ID);
                    if (e.Node.Id == maxIdChiTietCV)
                    {
                        // Them chi tiet cong viec moi
                        CongTac chiTietCV = new CongTac()
                        {
                            ID = CongTacList.Count,
                            ParentID = parentId,
                            TenCongViec = Constant.DEFAULT_WORK_DETAIL
                        };
                        CongTacList.Add(chiTietCV);
                    }
                }

                #endregion
            }
            else if (e.Column.FieldName.Equals(CongTacFieldName.KhoiLuong.ToString()) ||
                     e.Column.FieldName.Equals(CongTacFieldName.HSVL.ToString()) ||
                     e.Column.FieldName.Equals(CongTacFieldName.HSNC.ToString()) ||
                     e.Column.FieldName.Equals(CongTacFieldName.HSCM.ToString()))
            {
                #region Khoi luong, HS

                CongTac cvHienTai = CongTacList.Where(c => c.ID == e.Node.Id).FirstOrDefault();
                double ttvl = cvHienTai.TTVL;
                double ttnc = cvHienTai.TTNC;
                double ttcm = cvHienTai.TTCM;
                // norm calculate method
                if (lkePhuongPhapTinh.EditValue.ToString().Equals(Constant.DEFAULT_NORM))
                {
                    cvHienTai.DGVL *= cvHienTai.HSVL / HSVL;
                    cvHienTai.DGNC *= cvHienTai.HSNC / HSNC;
                    cvHienTai.DGCM *= cvHienTai.HSCM / HSCM;
                    cvHienTai.TTVL = cvHienTai.KhoiLuong * cvHienTai.DGVL.Value;
                    cvHienTai.TTNC = cvHienTai.KhoiLuong * cvHienTai.DGNC.Value;
                    cvHienTai.TTCM = cvHienTai.KhoiLuong * cvHienTai.DGCM.Value;
                    // update he so
                    HSVL = cvHienTai.HSVL;
                    HSNC = cvHienTai.HSNC;
                    HSCM = cvHienTai.HSCM;
                }
                else
                {
                    cvHienTai.TTVL = cvHienTai.KhoiLuong * cvHienTai.DGVL.Value * cvHienTai.HSVL;
                    cvHienTai.TTNC = cvHienTai.KhoiLuong * cvHienTai.DGNC.Value * cvHienTai.HSNC;
                    cvHienTai.TTCM = cvHienTai.KhoiLuong * cvHienTai.DGCM.Value * cvHienTai.HSCM;
                }

                cvHienTai.TongCong = cvHienTai.TTVL + cvHienTai.TTNC + cvHienTai.TTCM;

                AgentPrice += cvHienTai.TTVL - ttvl;
                PeoplePrice += cvHienTai.TTNC - ttnc;
                MachinePrice += cvHienTai.TTCM - ttcm;

                UpdatePriceStatus();
                // update nhom cong viec
                int nhomId = 0;
                if (e.Node.Level == TreeListLevel.CongViec)
                {
                    nhomId = e.Node.ParentNode.Id;
                }
                else
                {
                    nhomId = e.Node.ParentNode.ParentNode.Id;
                }
                UpdateNhomCV(nhomId);

                // Update DGDD & GDD
                double dgdd = HSDD * cvHienTai.TongCong;
                double gdd = dgdd * cvHienTai.KhoiLuong;
                cvHienTai.DGDD = dgdd;
                cvHienTai.GDD = gdd;
                // Update khoi luong can
                UpdateKLCan(cvHienTai);

                #endregion
            }
            else if (e.Column.FieldName.Equals(CongTacFieldName.MacVuaChon.ToString()))
            {
                #region MacVua

                string oldEditValue = rpiLkeMacVua.Tag.ToString();
                if (e.Value.ToString().Equals(oldEditValue))
                {
                    return;
                }
                // update hao phi cua mac vua
                CongTac cvHienTai = CongTacList.Where(c => c.ID == e.Node.Id).FirstOrDefault();
                double ttvl = cvHienTai.TTVL;
                var query = cvHienTai.HaoPhiCongViecs
                                     .Where(vua => vua.TenVatLieu.Trim()
                                     .Substring(0, 3)
                                     .Equals(Constant.VUA, StringComparison.OrdinalIgnoreCase));
                if (query.Count() > 0)
                {
                    DinhMuc hpVua = query.First();
                    List<DinhMuc> hpVuaList = DataUtilities.GetWasteListByMortar(e.Value.ToString(), hpVua.KhoiLuong, Province);
                    if (hpVuaList.Count > 0)
                    {
                        // Remove hp vua
                        cvHienTai.HaoPhiCongViecs.Remove(hpVua);
                        cvHienTai.DGVL -= hpVua.ThanhTien;
                        // Add hp vua list
                        foreach (DinhMuc vua in hpVuaList)
                        {
                            cvHienTai.DGVL += vua.ThanhTien;
                            cvHienTai.HaoPhiCongViecs.Add(vua);
                        }

                    }
                }
                else
                {
                    query = cvHienTai.HaoPhiCongViecs.Where(vua => vua.IsVua);
                    List<DinhMuc> hpVuaList = DataUtilities.GetWasteListByMortar(e.Value.ToString(), 1, Province);
                    if (query.Count() > 0 && hpVuaList.Count > 0)
                    {
                        // Remove current HP vua list
                        List<DinhMuc> currentHpVuaList = query.ToList();
                        foreach (DinhMuc vua in currentHpVuaList)
                        {
                            cvHienTai.HaoPhiCongViecs.Remove(vua);
                            cvHienTai.DGVL -= vua.ThanhTien;
                        }
                        // Add new HP vua list
                        foreach (DinhMuc vua in hpVuaList)
                        {
                            cvHienTai.HaoPhiCongViecs.Add(vua);
                            cvHienTai.DGVL += vua.ThanhTien;
                        }

                    }
                }

                cvHienTai.TTVL = cvHienTai.KhoiLuong * cvHienTai.DGVL.Value;
                AgentPrice += cvHienTai.TTVL - ttvl;

                UpdatePriceStatus();
                UpdateNhomCV(e.Node.ParentNode.Id);

                #endregion
            }
            trlCongViec.RefreshDataSource();
        }

        private void trlCongViec_ShowingEditor(object sender, CancelEventArgs e)
        {
            if (trlCongViec.FocusedNode.Level == TreeListLevel.CongViec)
            {
                if (!trlCongViec.FocusedColumn.FieldName.Equals(CongTacFieldName.MaHieu.ToString()) &&
                    trlCongViec.FocusedNode.GetDisplayText(0).Equals(Constant.DEFAULT_WORK))
                {
                    e.Cancel = true;
                }
                else if (trlCongViec.FocusedColumn.FieldName.Equals(CongTacFieldName.MacVuaChon.ToString()))
                {
                    CongTac cv = trlCongViec.GetDataRecordByNode(trlCongViec.FocusedNode) as CongTac;
                    if (cv != null)
                    {
                        e.Cancel = !cv.Vua;
                        rpiLkeMacVua.Tag = cv.MacVuaChon;
                    }
                }
            }
            if (trlCongViec.FocusedNode.Level == TreeListLevel.ChiTietCV)
            {
                if (!trlCongViec.FocusedColumn.FieldName.Equals(CongTacFieldName.TenCongViec.ToString()) &&
                    !trlCongViec.FocusedColumn.FieldName.Equals(CongTacFieldName.KhoiLuong.ToString()))
                {
                    e.Cancel = true;
                }
            }
        }

        private void trlCongViec_CustomDrawNodeCell(object sender, CustomDrawNodeCellEventArgs e)
        {
            if (e.Node.Level == TreeListLevel.NhomCV)
            {
                if (e.CellText.Equals(Constant.DEFAULT_WORKGROUP, StringComparison.OrdinalIgnoreCase))
                {
                    e.Appearance.Font = new Font(e.Appearance.Font.FontFamily, 8, FontStyle.Italic);
                    e.Appearance.ForeColor = Color.Silver;
                }
                else
                {
                    e.Appearance.Font = new Font(e.Appearance.Font.FontFamily, 12, FontStyle.Bold);
                    e.Appearance.ForeColor = Color.Blue;
                }
            }
            else if (e.Node.Level == TreeListLevel.CongViec)
            {
                if (e.Node.GetDisplayText(CongTacFieldName.MaHieu.ToString())
                     .Equals(Constant.DEFAULT_WORK, StringComparison.OrdinalIgnoreCase))
                {
                    e.Appearance.Font = new Font(e.Appearance.Font.FontFamily, 8, FontStyle.Italic);
                    e.Appearance.ForeColor = Color.Silver;
                }
                else
                {
                    e.Appearance.ForeColor = Color.Blue;
                }
                if (ThanhTienGoc.Count > 0)
                {
                    if (ThanhTienGoc.Keys.Contains(e.Node.GetDisplayText(CongTacFieldName.MaHieu.ToString())))
                    {
                        double tt = ThanhTienGoc.Where(t => t.Key == e.Node.GetDisplayText(CongTacFieldName.MaHieu.ToString())).First().Value;
                        if (tt != Convert.ToDouble(e.Node.GetValue(CongTacFieldName.TongCong.ToString())))
                        {
                            e.Appearance.ForeColor = Color.Red;
                        }
                    }
                    else
                    {
                        e.Appearance.ForeColor = Color.Red;
                    }
                }
            }
            else
            {
                if (e.Column.FieldName.Equals(CongTacFieldName.TenCongViec.ToString()) ||
                    e.Column.FieldName.Equals(CongTacFieldName.KhoiLuong.ToString()))
                {
                    if (e.Node.GetDisplayText(CongTacFieldName.TenCongViec.ToString())
                         .Equals(Constant.DEFAULT_WORK_DETAIL, StringComparison.OrdinalIgnoreCase))
                    {
                        e.Appearance.Font = new Font(e.Appearance.Font.FontFamily, 8, FontStyle.Italic);
                        e.Appearance.ForeColor = Color.Silver;
                    }
                    else
                    {
                        e.Appearance.Font = new Font(e.Appearance.Font.FontFamily, 10);
                        e.Appearance.ForeColor = Color.Black;
                    }
                    double value = 0;
                    if (double.TryParse(e.CellText, out value))
                    {
                        if (value == 0)
                            e.Appearance.ForeColor = Color.White;
                    }
                }
                else
                {
                    e.Appearance.ForeColor = Color.White;
                }
            }
        }

        private void trlCongViec_FocusedNodeChanged(object sender, FocusedNodeChangedEventArgs e)
        {
            if (e.Node != null && e.Node.Level == TreeListLevel.CongViec)
            {
                //CongTac cv = CongTacList.Where(c => c.ID == e.Node.Id).FirstOrDefault();
                CongTac cv = trlCongViec.GetDataRecordByNode(e.Node) as CongTac;
                if (cv != null)
                {
                    dgcHaoPhi.DataSource = cv.HaoPhiCongViecs;
                    HSVL = cv.HSVL;
                    HSNC = cv.HSNC;
                    HSCM = cv.HSCM;
                }
            }
        }

        private void trlCongViec_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Delete)
            {
                #region Delete

                if (trlCongViec.FocusedNode.GetDisplayText(CongTacFieldName.MaHieu.ToString()).Equals(Constant.DEFAULT_WORKGROUP) ||
                    trlCongViec.FocusedNode.GetDisplayText(CongTacFieldName.MaHieu.ToString()).Equals(Constant.DEFAULT_WORK) ||
                    trlCongViec.FocusedNode.GetDisplayText(CongTacFieldName.TenCongViec.ToString()).Equals(Constant.DEFAULT_WORK_DETAIL))
                {
                    return;
                }
                // update price before delete selected node
                foreach (TreeListNode node in trlCongViec.Selection)
                {
                    CongTac cv = trlCongViec.GetDataRecordByNode(node) as CongTac;
                    AgentPrice -= cv.TTVL;
                    PeoplePrice -= cv.TTNC;
                    MachinePrice -= cv.TTCM;
                    // update nhom cong viec
                    if (node.Level != TreeListLevel.NhomCV)
                    {
                        if (node.Level == TreeListLevel.CongViec)
                        {
                            //UpdateNhomCV(node.ParentNode.Id);
                        }
                        else
                        {
                            //UpdateNhomCV(node.ParentNode.ParentNode.Id);
                        }
                    }
                    //UndoCT.Push(new TrackingObject<CongTac>() { ObjectInfo = cv, Action = TrackingAction.Delete });
                    var query = ThanhTienGoc.Where(t => t.Key == cv.MaHieu);
                    if (query.Count() > 0)
                    {
                        ThanhTienGoc.Remove(cv.MaHieu);
                    }
                }
                trlCongViec.DeleteSelectedNodes();
                UpdateObjectIDAndParentID(trlCongViec.Nodes);
                dgcHaoPhi.DataSource = (trlCongViec.GetDataRecordByNode(trlCongViec.FocusedNode) as CongTac).HaoPhiCongViecs;

                UpdatePriceStatus();
                OldWorkCode = string.Empty;

                #endregion
            }
            else if (e.Control && e.KeyCode == Keys.Z)
            {
                #region Undo/Redo

                //TrackingObject<CongTac> cv = UndoCT.Pop();
                //if (cv != null)
                //{
                //    if (cv.Action == TrackingAction.Delete)
                //    {
                //        CongTacList.Add(cv.ObjectInfo);
                //    }
                //    else if (cv.Action == TrackingAction.Modify)
                //    {
                //        CongTac originalCv = CongTacList.Where(c => c.ID == cv.ObjectInfo.ID).FirstOrDefault();
                //        if (originalCv != null)
                //        {
                //            PropertiesMapper.CopyPropertiesFrom(originalCv, cv.ObjectInfo, ExcludedProperties);
                //        }
                //    }
                //    else
                //    {

                //    }
                //}

                #endregion
            }
            else if (e.Control && e.KeyCode == Keys.C)
            {

            }
            else if (e.Control && e.KeyCode == Keys.V)
            {

            }
        }

        private void dgvHaoPhi_CellValueChanged(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e)
        {
            if (e.Column.FieldName.Equals(DinhMucFieldName.KhoiLuong.ToString()) ||
                e.Column.FieldName.Equals(DinhMucFieldName.GiaThuc.ToString()))
            {
                if (e.Column.FieldName.Equals(DinhMucFieldName.GiaThuc.ToString()))
                {
                    IsEditNorm = true;
                }

                if (lkePhuongPhapTinh.EditValue.ToString().Equals(Constant.DEFAULT_NORM))
                {
                    #region Tinh theo dinh muc

                    CongTac cvHienTai = CongTacList.Where(c => c.ID == trlCongViec.FocusedNode.Id).First();
                    DinhMuc hpHienTai = dgvHaoPhi.GetRow(e.RowHandle) as DinhMuc;
                    double oldHpThanhTien = hpHienTai.ThanhTien;

                    hpHienTai.ThanhTien = hpHienTai.KhoiLuong * hpHienTai.GiaThuc;
                    hpHienTai.KhoiLuongCan = hpHienTai.KhoiLuong * cvHienTai.KhoiLuong;
                    // update don gia & thanh tien cua cong viec hien tai
                    if (hpHienTai.LoaiHaoPhi.Equals(WasteType.E.ToString()))
                    {
                        double ttnc = cvHienTai.TTNC;
                        cvHienTai.DGNC += hpHienTai.ThanhTien - oldHpThanhTien;
                        cvHienTai.TTNC = cvHienTai.KhoiLuong * cvHienTai.DGNC.Value * cvHienTai.HSNC;
                        PeoplePrice += cvHienTai.TTNC - ttnc;
                    }
                    else if (hpHienTai.LoaiHaoPhi.Equals(WasteType.F.ToString()))
                    {
                        double ttcm = cvHienTai.TTCM;
                        cvHienTai.DGCM += hpHienTai.ThanhTien - oldHpThanhTien;
                        cvHienTai.TTCM = cvHienTai.KhoiLuong * cvHienTai.DGCM.Value * cvHienTai.HSCM;
                        MachinePrice += cvHienTai.TTCM - ttcm;
                    }
                    else
                    {
                        double ttvl = cvHienTai.TTVL;
                        cvHienTai.DGVL += hpHienTai.ThanhTien - oldHpThanhTien;
                        cvHienTai.TTVL = cvHienTai.KhoiLuong * cvHienTai.DGVL.Value * cvHienTai.HSVL;
                        AgentPrice += cvHienTai.TTVL - ttvl;
                    }

                    UpdatePriceStatus();
                    UpdateNhomCV(cvHienTai.ParentID);
                    // Update DGDD & GDD
                    double dgdd = HSDD * cvHienTai.TongCong;
                    double gdd = dgdd * cvHienTai.KhoiLuong;
                    cvHienTai.DGDD = dgdd;
                    cvHienTai.GDD = gdd;
                    // Update khoi luong can
                    hpHienTai.KhoiLuongCan = hpHienTai.KhoiLuong * cvHienTai.KhoiLuong;

                    #endregion
                }
                else
                {
                    #region Tinh theo don gia tinh

                    DinhMuc hpHienTai = dgvHaoPhi.GetRow(e.RowHandle) as DinhMuc;
                    hpHienTai.ThanhTien = hpHienTai.KhoiLuong * hpHienTai.GiaThuc;

                    #endregion
                }
            }
            else if (e.Column.FieldName.Equals(DinhMucFieldName.TenVatLieu.ToString()))
            {
                if (e.RowHandle >= 0)
                {
                    DinhMuc hpHienTai = dgvHaoPhi.GetRow(e.RowHandle) as DinhMuc;
                    var query = TongHopHaoPhiList.Where(hp => hp.TenVatLieu.Equals(e.Value.ToString(), StringComparison.OrdinalIgnoreCase));
                    if (query.Count() > 0)
                    {
                        DinhMuc hp = query.First();
                        hpHienTai.MaVatLieu = hp.MaVatLieu;
                    }
                    else
                    {
                        Random rd = new Random();
                        DialogResult dlg = MessageBox.Show(MessageResource.CHANGE_TENVL, MessageResource.QUESTION,
                                                           MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
                        if (dlg == DialogResult.Yes)
                        {
                            foreach (CongTac cv in CongTacList)
                            {
                                var dm = cv.HaoPhiCongViecs.Where(h => h.TenVatLieu.Equals(TenVatLieu, StringComparison.OrdinalIgnoreCase));
                                if (dm.Count() > 0)
                                {
                                    foreach (DinhMuc hp in dm)
                                    {
                                        hp.MaVatLieu = string.Format(FormatString.TwoArgFormat, hpHienTai.MaVatLieu.Substring(0, 4),
                                                                     DataUtilities.GenerateRandomString(4, rd));
                                        hp.TenVatLieu = e.Value.ToString();
                                    }
                                }
                            }
                            hpHienTai.MaVatLieu = string.Format(FormatString.TwoArgFormat, hpHienTai.MaVatLieu.Substring(0, 4),
                                                                        DataUtilities.GenerateRandomString(4, rd));
                        }
                        else if (dlg == DialogResult.No)
                        {
                            hpHienTai.MaVatLieu = string.Format(FormatString.TwoArgFormat, hpHienTai.MaVatLieu.Substring(0, 4),
                                                                DataUtilities.GenerateRandomString(4, rd));
                        }
                        else
                        {
                            hpHienTai.TenVatLieu = TenVatLieu;
                        }
                    }
                }
            }
            else if (e.Column.FieldName == DinhMucFieldName.MaVatLieu.ToString())
            {
                CongTac cv = trlCongViec.GetDataRecordByNode(trlCongViec.FocusedNode) as CongTac;
                if (cv != null)
                {
                    string maHP = e.Value.ToString();
                    DinhMuc dm = DeluxeContext.DinhMucs.Where(d => d.MaVatLieu == maHP).FirstOrDefault();
                    DinhMuc hp = cv.HaoPhiCongViecs.Where(h => h.MaVatLieu == e.Value.ToString()).FirstOrDefault();
                    if (hp == null) hp = new DinhMuc();
                    hp.DonVi = dm.DonVi;
                    hp.TenVatLieu = dm == null ? dm.TenVatLieu : "Nhập tên vật liệu mới";
                    hp.KhoiLuong = dm.KhoiLuong;
                }
            }
        }

        private void dgvHaoPhi_FocusedRowChanged(object sender, DevExpress.XtraGrid.Views.Base.FocusedRowChangedEventArgs e)
        {
            DinhMuc hp = dgvHaoPhi.GetRow(e.FocusedRowHandle) as DinhMuc;
            if (hp != null)
            {
                TenVatLieu = hp.TenVatLieu;
            }
        }

        private void dgvHaoPhi_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Delete)
            {
                DinhMuc hp = dgvHaoPhi.GetRow(dgvHaoPhi.FocusedRowHandle) as DinhMuc;
                if (hp != null)
                {
                    if (lkePhuongPhapTinh.EditValue.ToString().Equals(Constant.DEFAULT_NORM))
                    {
                        #region Tinh theo dinh muc

                        CongTac cvHienTai = CongTacList.Where(c => c.ID == trlCongViec.FocusedNode.Id).First();
                        // update don gia & thanh tien cua cong viec hien tai
                        if (hp.LoaiHaoPhi.Equals(WasteType.E.ToString()))
                        {
                            double ttnc = cvHienTai.TTNC;
                            cvHienTai.DGNC -= hp.ThanhTien;
                            cvHienTai.TTNC = cvHienTai.KhoiLuong * cvHienTai.DGNC.Value * cvHienTai.HSNC;
                            PeoplePrice += cvHienTai.TTNC - ttnc;
                        }
                        else if (hp.LoaiHaoPhi.Equals(WasteType.F.ToString()))
                        {
                            double ttcm = cvHienTai.TTCM;
                            cvHienTai.DGCM -= hp.ThanhTien;
                            cvHienTai.TTCM = cvHienTai.KhoiLuong * cvHienTai.DGCM.Value * cvHienTai.HSCM;
                            MachinePrice += cvHienTai.TTCM - ttcm;
                        }
                        else
                        {
                            double ttvl = cvHienTai.TTVL;
                            cvHienTai.DGVL -= hp.ThanhTien;
                            cvHienTai.TTVL = cvHienTai.KhoiLuong * cvHienTai.DGVL.Value * cvHienTai.HSVL;
                            AgentPrice += cvHienTai.TTVL - ttvl;
                        }

                        UpdatePriceStatus();
                        UpdateNhomCV(cvHienTai.ParentID);
                        // Update DGDD & GDD
                        double dgdd = HSDD * cvHienTai.TongCong;
                        double gdd = dgdd * cvHienTai.KhoiLuong;
                        cvHienTai.DGDD = dgdd;
                        cvHienTai.GDD = gdd;

                        #endregion
                    }
                    dgvHaoPhi.DeleteRow(dgvHaoPhi.FocusedRowHandle);
                }
            }
        }

        private void rpiTxtMaHieu_Enter(object sender, EventArgs e)
        {
            TextEdit txtMaHieu = sender as TextEdit;
            if (txtMaHieu.Text.Equals(Constant.DEFAULT_WORKGROUP) ||
                txtMaHieu.Text.Equals(Constant.DEFAULT_WORK))
            {
                txtMaHieu.Text = string.Empty;
                FocusedNewRow = true;
            }
            else
            {
                OldWorkCode = txtMaHieu.Text;
                FocusedNewRow = false;
            }
        }

        private void rpiTxtMaHieu_Leave(object sender, EventArgs e)
        {
            if (trlCongViec.FocusedNode != null)
            {
                TextEdit txtMaHieu = sender as TextEdit;
                if (string.IsNullOrEmpty(txtMaHieu.Text))
                {
                    if (trlCongViec.FocusedNode.Level == TreeListLevel.NhomCV)
                    {
                        trlCongViec.FocusedNode.SetValue(CongTacFieldName.MaHieu.ToString(), Constant.DEFAULT_WORKGROUP);
                    }
                    else
                    {
                        trlCongViec.FocusedNode.SetValue(CongTacFieldName.MaHieu.ToString(), Constant.DEFAULT_WORK);
                    }
                }
            }
        }

        private void rpiTxtTenCongViec_Enter(object sender, EventArgs e)
        {
            TextEdit txtTenCV = sender as TextEdit;
            if (txtTenCV.Text.Equals(Constant.DEFAULT_WORK_DETAIL))
            {
                txtTenCV.Text = string.Empty;
                FocusedNewRow = true;
            }
            else
            {
                FocusedNewRow = false;
            }
        }

        private void rpiTxtTenCongViec_Leave(object sender, EventArgs e)
        {
            TextEdit txtMaHieu = sender as TextEdit;
            if (string.IsNullOrEmpty(txtMaHieu.Text))
            {
                if (trlCongViec.FocusedNode.Level == TreeListLevel.ChiTietCV)
                {
                    trlCongViec.FocusedNode.SetValue(CongTacFieldName.TenCongViec.ToString(), Constant.DEFAULT_WORK_DETAIL);
                }
            }
        }

        private void rpiTxtTenCongViec_KeyUp(object sender, KeyEventArgs e)
        {
            TextEdit txtTenCV = sender as TextEdit;
            CongTac cv = trlCongViec.GetDataRecordByNode(trlCongViec.FocusedNode.ParentNode) as CongTac;
            if (!e.Shift && e.KeyCode == Keys.Oemplus)
            {
                double kl = DataUtilities.CalculateWeight(txtTenCV.Text);
                CongTac chitiet = trlCongViec.GetDataRecordByNode(trlCongViec.FocusedNode) as CongTac;
                chitiet.KhoiLuong = kl;
                chitiet.TenCongViec = txtTenCV.Text;
                if (cv != null && AutoCalculateKL)
                {
                    cv.KhoiLuong = CongTacList.Where(c => c.ParentID == cv.ID).Sum(c => c.KhoiLuong);
                    // update total price
                    UpdatePriceWhenKLChanged(trlCongViec.FocusedNode.ParentNode);
                }
                SendKeys.Send(SymbolCode.KEY_TAB);
            }
        }

        private void rpiTxtIntegerNumber_KeyUp(object sender, KeyEventArgs e)
        {
            TextEdit txtNumber = sender as TextEdit;
            if (e.Control && e.KeyCode == Keys.C)
            {
                Clipboard.SetText(DTDConvert.ConvertToNumericFormat(txtNumber.SelectedText));
            }
        }

        private void CongTacList_ListChanged(object sender, ListChangedEventArgs e)
        {
            FileSaved = false;
            StatusFile = FileStatus.Editing;
        }

        /// <summary>
        /// Update kl can cua cv hien tai
        /// </summary>
        /// <param name="cvHienTai">Cong viec hien tai</param>
        private void UpdateKLCan(CongTac cvHienTai)
        {
            if (cvHienTai.HaoPhiCongViecs.Count > 0)
            {
                foreach (DinhMuc hp in cvHienTai.HaoPhiCongViecs)
                {
                    if (hp.LoaiHaoPhi.Equals(WasteType.E.ToString()))
                    {
                        hp.KhoiLuongCan = cvHienTai.KhoiLuong * cvHienTai.HSNC * hp.KhoiLuong;
                    }
                    else if (hp.LoaiHaoPhi.Equals(WasteType.F.ToString()))
                    {
                        hp.KhoiLuongCan = cvHienTai.KhoiLuong * cvHienTai.HSCM * hp.KhoiLuong;
                    }
                    else
                    {
                        hp.KhoiLuongCan = cvHienTai.KhoiLuong * cvHienTai.HSVL * hp.KhoiLuong;
                    }
                }
            }
        }

        /// <summary>
        /// Update id and parent id of tree list view to binding list
        /// </summary>
        /// <param name="nodes">Parent nodes in level 0</param>
        private void UpdateObjectIDAndParentID(TreeListNodes nodes)
        {
            foreach (TreeListNode node in nodes)
            {
                CongTac cv = trlCongViec.GetDataRecordByNode(node) as CongTac;
                if (cv.ID != node.Id)
                {
                    cv.ID = node.Id;
                }
                if (node.ParentNode != null)
                {
                    if (cv.ParentID != node.ParentNode.Id)
                    {
                        cv.ParentID = node.ParentNode.Id;
                    }
                }
                else
                {
                    cv.ParentID = -1;
                }
                // update child node
                if (node.HasChildren)
                {
                    UpdateObjectIDAndParentID(node.Nodes);
                }
            }
        }

        /// <summary>
        /// Update thanh tien cho nhom cong viec
        /// </summary>
        /// <param name="id">Nhom CV Id</param>
        private void UpdateNhomCV(int id)
        {
            CongTac nhomCV = CongTacList.Where(c => c.ID == id).FirstOrDefault();
            double ttvl = CongTacList.Where(c => c.ParentID == id).Sum(c => c.TTVL);
            double ttnc = CongTacList.Where(c => c.ParentID == id).Sum(c => c.TTNC);
            double ttcm = CongTacList.Where(c => c.ParentID == id).Sum(c => c.TTCM);
            string tt = string.Format(Constant.NHOM_TT, ttvl.ToString(Constant.INT_FORMAT),
                                                        ttnc.ToString(Constant.INT_FORMAT),
                                                        ttcm.ToString(Constant.INT_FORMAT));
            if (ttvl > 0 || ttnc > 0 || ttcm > 0)
            {
                string tmp = nhomCV.MaHieu;
                if (tmp.Contains(Constant.NHOM_TT_HEAD))
                {
                    tmp = tmp.Substring(tmp.LastIndexOf(Constant.NHOM_TT_HEAD));
                    nhomCV.MaHieu = nhomCV.MaHieu.Replace(tmp, tt);
                }
                else
                {
                    nhomCV.MaHieu += tt;
                }
            }
        }

        private void UpdatePriceWhenKLChanged(TreeListNode cvNode)
        {
            CongTac cvHienTai = CongTacList.Where(c => c.ID == cvNode.Id).FirstOrDefault();
            double ttvl = cvHienTai.TTVL;
            double ttnc = cvHienTai.TTNC;
            double ttcm = cvHienTai.TTCM;
            // norm calculate method
            if (lkePhuongPhapTinh.EditValue.ToString().Equals(Constant.DEFAULT_NORM))
            {
                cvHienTai.DGVL *= cvHienTai.HSVL / HSVL;
                cvHienTai.DGNC *= cvHienTai.HSNC / HSNC;
                cvHienTai.DGCM *= cvHienTai.HSCM / HSCM;
                cvHienTai.TTVL = cvHienTai.KhoiLuong * cvHienTai.DGVL.Value;
                cvHienTai.TTNC = cvHienTai.KhoiLuong * cvHienTai.DGNC.Value;
                cvHienTai.TTCM = cvHienTai.KhoiLuong * cvHienTai.DGCM.Value;
                // update he so
                HSVL = cvHienTai.HSVL;
                HSNC = cvHienTai.HSNC;
                HSCM = cvHienTai.HSCM;
            }
            else
            {
                cvHienTai.TTVL = cvHienTai.KhoiLuong * cvHienTai.DGVL.Value * cvHienTai.HSVL;
                cvHienTai.TTNC = cvHienTai.KhoiLuong * cvHienTai.DGNC.Value * cvHienTai.HSNC;
                cvHienTai.TTCM = cvHienTai.KhoiLuong * cvHienTai.DGCM.Value * cvHienTai.HSCM;
            }

            cvHienTai.TongCong = cvHienTai.TTVL + cvHienTai.TTNC + cvHienTai.TTCM;

            AgentPrice += cvHienTai.TTVL - ttvl;
            PeoplePrice += cvHienTai.TTNC - ttnc;
            MachinePrice += cvHienTai.TTCM - ttcm;

            UpdatePriceStatus();
            // update nhom cong viec
            int nhomId = 0;
            if (cvNode.Level == TreeListLevel.CongViec)
            {
                nhomId = cvNode.ParentNode.Id;
            }
            else
            {
                nhomId = cvNode.ParentNode.ParentNode.Id;
            }
            //UpdateNhomCV(nhomId);

            // Update DGDD & GDD
            double dgdd = HSDD * cvHienTai.TongCong;
            double gdd = dgdd * cvHienTai.KhoiLuong;
            cvHienTai.DGDD = dgdd;
            cvHienTai.GDD = gdd;
            // Update khoi luong can
            UpdateKLCan(cvHienTai);
        }

        #endregion

        #region Tab3

        /// <summary>
        /// Initialize tab3
        /// </summary>
        private void InitializeTab3()
        {
            trlTongHopHP.DataSource = TongHopHaoPhiList;
            // Assign column edit            
            trlTongHopHP.Columns["GiaThuc"].ColumnEdit = rpiTxtIntegerNumber;
            trlTongHopHP.Columns["GiaGoc"].ColumnEdit = rpiTxtIntegerNumber;
            trlTongHopHP.Columns["DGSauThue"].ColumnEdit = rpiTxtIntegerNumber;
            trlTongHopHP.Columns["KhoiLuongCan"].ColumnEdit = rpiTxtDoubleNumber;

            trlTongHopHP.CustomDrawNodeCell += new CustomDrawNodeCellEventHandler(trlTongHopHP_CustomDrawNodeCell);
        }

        private void trlTongHopHP_CustomDrawNodeCell(object sender, CustomDrawNodeCellEventArgs e)
        {
            if (e.Node.Level == TreeListLevel.NhomCV)
            {
                e.Appearance.Font = new Font(e.Appearance.Font.FontFamily, 12, FontStyle.Bold);
                e.Appearance.ForeColor = Color.Blue;
            }
            else if (e.Node.Level == TreeListLevel.CongViec)
            {
                e.Appearance.ForeColor = Color.Blue;
            }
            else
            {
                e.Appearance.Font = new Font(e.Appearance.Font.FontFamily, 10);
                e.Appearance.ForeColor = Color.Black;
            }
        }

        /// <summary>
        /// Update tong hop hao phi list
        /// </summary>
        private void UpdateTongHopHaoPhiList()
        {
            if (CongTacList.Count <= 1)
                return;

            TongHopHaoPhiList.Clear();
            DinhMuc vl = new DinhMuc() { ID = 0, ParentID = -1, MaVatLieu = Constant.NHOM_VL };
            DinhMuc nc = new DinhMuc() { ID = 1, ParentID = -1, MaVatLieu = Constant.NHOM_NC };
            DinhMuc cm = new DinhMuc() { ID = 2, ParentID = -1, MaVatLieu = Constant.NHOM_CM };
            TongHopHaoPhiList.Add(vl);
            TongHopHaoPhiList.Add(nc);
            TongHopHaoPhiList.Add(cm);
            foreach (CongTac cv in CongTacList)
            {
                foreach (DinhMuc dm in cv.HaoPhiCongViecs)
                {
                    var query = TongHopHaoPhiList.Where(d => d.MaVatLieu.Equals(dm.MaVatLieu));
                    if (query.Count() > 0)
                    {
                        DinhMuc hp = query.FirstOrDefault();

                        DinhMuc child = new DinhMuc();
                        child.ID = TongHopHaoPhiList.Count;
                        child.ParentID = hp.ID;
                        child.MaVatLieu = cv.MaHieu;
                        child.TenVatLieu = cv.TenCongViec;
                        child.DonVi = cv.DonVi;
                        child.KhoiLuongCan = cv.KhoiLuong * dm.KhoiLuong;
                        child.KLTT = string.Format("{0} * {1} = {2}", cv.KhoiLuong.ToString(Constant.FLOAT_FORMAT),
                                                                      dm.KhoiLuong.ToString(Constant.FLOAT_FORMAT),
                                                                      child.KhoiLuongCan.ToString(Constant.FLOAT_FORMAT));
                        child.STT = cv.STT.Value;
                        TongHopHaoPhiList.Add(child);

                        // update khoi luong can
                        hp.KhoiLuongCan = TongHopHaoPhiList.Where(h => h.ParentID == hp.ID).Sum(h => h.KhoiLuongCan);
                        hp.KLTT = hp.KhoiLuongCan.ToString(Constant.FLOAT_FORMAT);
                        hp.GiaGoc = hp.KhoiLuongCan * hp.GiaThuc;
                        hp.DGSauThue = hp.GiaThuc * 1.1;
                    }
                    else
                    {
                        DinhMuc hp = new DinhMuc();
                        PropertiesMapper.CopyPropertiesFrom(hp, dm, ExcludedProperties);
                        hp.ID = TongHopHaoPhiList.Count;
                        hp.ParentID = hp.LoaiHaoPhi.Equals(WasteType.E.ToString()) ? nc.ID :
                                     (hp.LoaiHaoPhi.Equals(WasteType.F.ToString()) ? cm.ID : vl.ID);
                        hp.KhoiLuongCan = cv.KhoiLuong * dm.KhoiLuong;
                        hp.KLTT = hp.KhoiLuongCan.ToString(Constant.FLOAT_FORMAT);
                        hp.GiaGoc = hp.KhoiLuongCan * hp.GiaThuc;
                        hp.DGSauThue = hp.GiaThuc * 1.1;
                        TongHopHaoPhiList.Add(hp);

                        DinhMuc child = new DinhMuc();
                        child.ID = TongHopHaoPhiList.Count;
                        child.ParentID = hp.ID;
                        child.MaVatLieu = cv.MaHieu;
                        child.TenVatLieu = cv.TenCongViec;
                        child.DonVi = cv.DonVi;
                        child.KhoiLuongCan = cv.KhoiLuong * dm.KhoiLuong;
                        child.KLTT = string.Format("{0} * {1} = {2}", cv.KhoiLuong.ToString(Constant.FLOAT_FORMAT),
                                                                      dm.KhoiLuong.ToString(Constant.FLOAT_FORMAT),
                                                                      child.KhoiLuongCan.ToString(Constant.FLOAT_FORMAT));
                        child.STT = cv.STT.Value;
                        TongHopHaoPhiList.Add(child);
                    }
                }
            }
            vl.MaVatLieu = string.Format(Constant.NHOM_VL,
                                    TongHopHaoPhiList.Where(h => h.ParentID == vl.ID)
                                                     .Sum(h => h.GiaGoc)
                                                     .ToString(Constant.INT_FORMAT));
            nc.MaVatLieu = string.Format(Constant.NHOM_NC,
                                    TongHopHaoPhiList.Where(h => h.ParentID == nc.ID)
                                                     .Sum(h => h.GiaGoc)
                                                     .ToString(Constant.INT_FORMAT));
            cm.MaVatLieu = string.Format(Constant.NHOM_CM,
                                    TongHopHaoPhiList.Where(h => h.ParentID == cm.ID)
                                                     .Sum(h => h.GiaGoc)
                                                     .ToString(Constant.INT_FORMAT));
            trlTongHopHP.RefreshDataSource();
        }

        #endregion

        #region Tab4

        private void InitializeTab4()
        {
            // Load default chiphixaydung from database
            ChiPhiXayDungList.Clear();
            foreach (ChiPhiXayDung cpxd in DeluxeContext.ChiPhiXayDungs)
            {
                ChiPhiXayDung copy = new ChiPhiXayDung();
                PropertiesMapper.CopyPropertiesFrom(copy, cpxd);
                ChiPhiXayDungList.Add(copy);
            }
            dgcTHCPXD.DataSource = ChiPhiXayDungList;

            // Event handler
            dgvTHCPXD.KeyUp += new KeyEventHandler(dgvTHCPXD_KeyUp);
            rpiBtnCalculateMethod.ButtonClick += new ButtonPressedEventHandler(rpiBtnCalculateMethod_ButtonClick);

            ChiPhiXayDungList.ListChanged += new ListChangedEventHandler(ChiPhiXayDungList_ListChanged);

            // Tinh he so day du
            AgentPrice = Constant.DEFAULT_PRICE;
            PeoplePrice = Constant.DEFAULT_PRICE;
            MachinePrice = Constant.DEFAULT_PRICE;
            double totalPrice = CalculateTotalPrice();
            double agent = ChiPhiXayDungList.Where(c => c.KyHieu.Equals(Constant.CPVL)).First().ThanhTien.Value;
            double people = ChiPhiXayDungList.Where(c => c.KyHieu.Equals(Constant.CPNC)).First().ThanhTien.Value;
            double machine = ChiPhiXayDungList.Where(c => c.KyHieu.Equals(Constant.CPCM)).First().ThanhTien.Value;
            HSDD = totalPrice / (agent + people + machine);
            AgentPrice = 0;
            PeoplePrice = 0;
            MachinePrice = 0;
            ResetTotalPrice();
        }

        private void ChiPhiXayDungList_ListChanged(object sender, ListChangedEventArgs e)
        {
            FileSaved = false;
            StatusFile = FileStatus.Editing;
        }

        private void dgvTHCPXD_KeyUp(object sender, KeyEventArgs e)
        {
            int index = dgvTHCPXD.GetDataSourceRowIndex(dgvTHCPXD.FocusedRowHandle);
            if (e.KeyCode == Keys.Delete)
            {
                if (index >= 0)
                {
                    string symbol = string.Format("[{0}]", ChiPhiXayDungList[index].KyHieu);
                    if (symbol.Equals(SymbolCode.Cpvl) || symbol.Equals(SymbolCode.Cpnc) ||
                        symbol.Equals(SymbolCode.Cpcm) || symbol.Equals(SymbolCode.T) || symbol.Equals(SymbolCode.Z))
                    {
                        ((Startup)this.ParentForm).ShowErrorMessage(MessageResource.CANNOT_DELETE_ROW);
                    }
                    else
                    {
                        ChiPhiXayDungList.RemoveAt(index);
                        UpdatePriceStatus();
                    }
                }
            }
            else if (e.Control && e.KeyCode == Keys.I)
            {
                if (index >= 0)
                {
                    if (index < ChiPhiXayDungList.Count - 1)
                    {
                        ChiPhiXayDungList.Insert(index + 1, new ChiPhiXayDung());
                    }
                    else
                    {
                        ChiPhiXayDungList.Insert(index, new ChiPhiXayDung());
                    }
                }
                else
                {
                    ChiPhiXayDungList.Insert(0, new ChiPhiXayDung());
                }
            }
            else if (e.Control && e.KeyCode == Keys.C)
            {
                ChiPhiXayDungCopy = new ChiPhiXayDung();
                PropertiesMapper.CopyPropertiesFrom(ChiPhiXayDungCopy, ChiPhiXayDungList[index]);
            }
            else if (e.Control && e.KeyCode == Keys.V)
            {
                if (index >= 0)
                {
                    if (index < ChiPhiXayDungList.Count - 1)
                    {
                        ChiPhiXayDungList.Insert(index + 1, ChiPhiXayDungCopy);
                    }
                    else
                    {
                        ChiPhiXayDungList.Insert(index, ChiPhiXayDungCopy);
                    }
                }
                else
                {
                    ChiPhiXayDungList.Insert(0, ChiPhiXayDungCopy);
                }
            }
        }

        private void rpiBtnCalculateMethod_ButtonClick(object sender, ButtonPressedEventArgs e)
        {
            int index = dgvTHCPXD.GetDataSourceRowIndex(dgvTHCPXD.FocusedRowHandle);
            List<string> symbols = new List<string>() { SymbolCode.A1, SymbolCode.B1, SymbolCode.C1 };
            if (index >= 0)
            {
                for (int i = 0; i < index; i++)
                {
                    symbols.Add(string.Format("[{0}]", ChiPhiXayDungList[i].KyHieu));
                }
                guiExpressionEditor editor = new guiExpressionEditor(ChiPhiXayDungList[index].CongThucTinh, symbols);
                if (editor.ShowDialog() == DialogResult.OK)
                {
                    ChiPhiXayDungList[index].CongThucTinh = editor.Expression;
                    UpdatePriceStatus();
                    // Tinh he so day du
                    double totalPrice = CalculateTotalPrice();
                    double agent = ChiPhiXayDungList.Where(c => c.KyHieu.Equals(Constant.CPVL)).First().ThanhTien.Value;
                    double people = ChiPhiXayDungList.Where(c => c.KyHieu.Equals(Constant.CPNC)).First().ThanhTien.Value;
                    double machine = ChiPhiXayDungList.Where(c => c.KyHieu.Equals(Constant.CPCM)).First().ThanhTien.Value;
                    HSDD = totalPrice / (agent + people + machine);
                }
                dgcTHCPXD.RefreshDataSource();
            }
        }

        /// <summary>
        /// Calculate building item price
        /// </summary>
        /// <param name="expression">Item calculate method</param>
        /// <returns>Price of item building list</returns>
        private double CalculateBuildingPrice(string expression)
        {
            double result = 0;
            if (string.IsNullOrEmpty(expression))
            {
                return 0;
            }
            if (expression.Contains(Constant.DEFAULT_CPVL))
            {
                expression = expression.Replace(Constant.DEFAULT_CPVL, AgentPrice.ToString());
            }
            if (expression.Contains(Constant.DEFAULT_CPNC))
            {
                expression = expression.Replace(Constant.DEFAULT_CPNC, PeoplePrice.ToString());
            }
            if (expression.Contains(Constant.DEFAULT_CPCM))
            {
                expression = expression.Replace(Constant.DEFAULT_CPCM, MachinePrice.ToString());
            }
            foreach (ChiPhiXayDung cpxd in ChiPhiXayDungList)
            {
                if (expression.Contains(string.Format("[{0}]", cpxd.KyHieu)))
                {
                    expression = expression.Replace(string.Format("[{0}]", cpxd.KyHieu), cpxd.ThanhTien.ToString());
                }
            }
            // replace string between "[" and "]" to "0" after formularizing expression
            string pattern = @"\[.*?\]";
            Regex re = new Regex(pattern);
            MatchCollection mc = re.Matches(expression);
            foreach (Match m in mc)
            {
                expression = expression.Replace(m.Value, Constant.ZERO);
            }
            try
            {
                result = DataUtilities.CalculateExpression(expression.Replace(',', '.'));
            }
            catch
            {
                result = 0;
            }
            return result;
        }

        /// <summary>
        /// Calculate total price
        /// </summary>
        /// <returns>Total price</returns>
        private double CalculateTotalPrice()
        {
            foreach (ChiPhiXayDung cpxd in ChiPhiXayDungList)
            {
                cpxd.ThanhTien = CalculateBuildingPrice(cpxd.CongThucTinh);
            }
            double totalPrice = ChiPhiXayDungList.Last().ThanhTien.Value;
            if (totalPrice > 0)
            {
                foreach (ChiPhiXayDung cpxd in ChiPhiXayDungList)
                {
                    cpxd.Gxdcpt = cpxd.ThanhTien / totalPrice;
                }
            }
            return totalPrice;
        }

        /// <summary>
        /// Reset total price for tab4
        /// </summary>
        private void ResetTotalPrice()
        {
            foreach (ChiPhiXayDung cpxd in ChiPhiXayDungList)
            {
                cpxd.ThanhTien = 0;
            }
        }

        #endregion

        #endregion

        #region Public method

        /// <summary>
        /// Load data from xml file
        /// </summary>
        /// <param name="filePath">Xml file path</param>
        public void LoadDTDFromFile(string filePath)
        {
            XDocument doc = XDocument.Load(filePath);
            if (doc == null)
            {
                ((Startup)this.ParentForm).ShowErrorMessage(MessageResource.LOAD_ERROR);
                return;
            }

            #region Tab1

            ThongTinDT ttDT = DataUtilities.LoadTab1(doc);
            bteTenDuAn.EditValue = ttDT.TenDuAn;
            txtTenCongTrinh.Text = ttDT.TenCongTrinh;
            txtDiaDiemCongTrinh.Text = ttDT.DiaDiemCongTrinh;
            txtTenChuDauTu.Text = ttDT.TenChuDauTu;
            txtTenNhaThau.Text = ttDT.TenNhaThau;
            txtTenChuTri.Text = ttDT.TenChuTriLapDauTu;
            txtKSDG.Text = ttDT.KSDG;
            txtHang.Text = ttDT.Hang;
            lkeLoaiCongTrinh.EditValue = ttDT.LoaiHinhChinh;
            lkeCapCongTrinh.EditValue = ttDT.CapCongTrinh;
            lkeSoBuocThietKe.EditValue = ttDT.SoBuocThietKe;
            lkePhuongPhapTinh.EditValue = ttDT.PhuongPhapTinh;
            lkeThuocTinh.EditValue = ttDT.ThuocTinh;
            lkeDuToanThamTra.EditValue = ttDT.DuToanHayThamTra;
            dteNgayLap.DateTime = ttDT.NgayLap;
            dteNgaySua.DateTime = ttDT.NgaySua;
            txtMatKhau.Text = ttDT.MatKhau;
            chkHoTroNhap.Checked = ttDT.HoTroNhap;

            AgentPrice = ttDT.DGVL;
            PeoplePrice = ttDT.DGNC;
            MachinePrice = ttDT.DGCM;
            beiTxtAgentPrice.EditValue = ttDT.TTVL;
            beiTxtPeoplePrice.EditValue = ttDT.TTNC;
            beiTxtMachinePrice.EditValue = ttDT.TTCM;
            beiTxtTotalPrice.EditValue = ttDT.TongCong;

            #endregion

            #region Tab2

            CongTacList.Clear();
            CongTacList = DataUtilities.LoadTab2(doc);
            trlCongViec.DataSource = CongTacList;
            AutoIncrease = CongTacList.Where(c => c.STT.HasValue).Max(c => c.STT.Value);

            var tmp = CongTacList.Select(c => new { c.MaHieu, c.TongCong });
            if (tmp.Count() > 0)
            {
                foreach (var tt in tmp)
                {
                    if (!ThanhTienGoc.ContainsKey(tt.MaHieu))
                    {
                        ThanhTienGoc.Add(tt.MaHieu, tt.TongCong);
                    }
                }
            }

            #endregion

            #region Tab4

            ChiPhiXayDungList = DataUtilities.LoadTab4(doc);
            dgcTHCPXD.DataSource = ChiPhiXayDungList;

            // Tinh he so day du
            double totalPrice = CalculateTotalPrice();
            double agent = ChiPhiXayDungList.Where(c => c.KyHieu.Equals(Constant.CPVL)).First().ThanhTien.Value;
            double people = ChiPhiXayDungList.Where(c => c.KyHieu.Equals(Constant.CPNC)).First().ThanhTien.Value;
            double machine = ChiPhiXayDungList.Where(c => c.KyHieu.Equals(Constant.CPCM)).First().ThanhTien.Value;
            HSDD = totalPrice / (agent + people + machine);

            #endregion
        }

        /// <summary>
        /// Save data to xml file
        /// </summary>
        /// <param name="filePath">Xml file path</param>
        public void SaveDTDToFile(string filePath)
        {
            XDocument doc = new XDocument(new XDeclaration(XMLFile.VERSION, XMLFile.ENCODING, XMLFile.STANDALONE));
            // Root node
            doc.Add(new XElement(XMLFile.ROOT,
                        new XElement(XMLFile.TAB1),
                        new XElement(XMLFile.TAB2),
                        new XElement(XMLFile.TAB4),
                        new XElement(XMLFile.TAB5),
                        new XElement(XMLFile.TAB6),
                        new XElement(XMLFile.TAB7),
                        new XElement(XMLFile.TAB8),
                        new XElement(XMLFile.TAB9),
                        new XElement(XMLFile.STATUS)));

            // Save tab1
            ThongTinDT ttDT = new ThongTinDT()
            {
                TenDuAn = bteTenDuAn.Text,
                TenCongTrinh = txtTenCongTrinh.Text,
                DiaDiemCongTrinh = txtDiaDiemCongTrinh.Text,
                TenChuDauTu = txtTenChuDauTu.Text,
                TenNhaThau = txtTenNhaThau.Text,
                TenChuTriLapDauTu = txtTenChuTri.Text,
                KSDG = txtKSDG.Text,
                Hang = txtHang.Text,
                LoaiHinhChinh = lkeLoaiCongTrinh.EditValue.ToString(),
                CapCongTrinh = lkeCapCongTrinh.EditValue.ToString(),
                SoBuocThietKe = lkeSoBuocThietKe.EditValue.ToString(),
                PhuongPhapTinh = lkePhuongPhapTinh.EditValue.ToString(),
                ThuocTinh = lkeThuocTinh.EditValue.ToString(),
                DuToanHayThamTra = lkeDuToanThamTra.EditValue.ToString(),
                NgayLap = dteNgayLap.DateTime,
                NgaySua = dteNgaySua.DateTime,
                MatKhau = txtMatKhau.Text,
                HoTroNhap = chkHoTroNhap.Checked,
                DGVL = AgentPrice,
                DGNC = PeoplePrice,
                DGCM = MachinePrice,
                TTVL = Convert.ToDouble(beiTxtAgentPrice.EditValue),
                TTNC = Convert.ToDouble(beiTxtPeoplePrice.EditValue),
                TTCM = Convert.ToDouble(beiTxtMachinePrice.EditValue),
                TongCong = Convert.ToDouble(beiTxtTotalPrice.EditValue)
            };
            DataUtilities.SaveTab1(doc, ttDT);

            // Save tab2
            DataUtilities.SaveTab2(doc, CongTacList);
            // Save status price
            DataUtilities.SaveStatusPrice(doc, ttDT);
            // Save tab4
            DataUtilities.SaveTab4(doc, ChiPhiXayDungList);
            doc.Save(filePath);
        }

        /// <summary>
        /// Save norm to database
        /// </summary>
        public void SaveNorm()
        {
            StringBuilder updateTdvt = new StringBuilder();
            StringBuilder updateProvince = new StringBuilder();
            foreach (CongTac cv in CongTacList)
            {
                foreach (DinhMuc hp in cv.HaoPhiCongViecs)
                {
                    string query = string.Format(QueryString.UPDATE_TDVT, hp.GiaThuc, hp.MaVatLieu);
                    updateTdvt.Append(query);
                    string query1 = string.Format(QueryString.UPDATE_PROVINCE, Province, hp.GiaThuc, hp.MaVatLieu);
                    updateProvince.Append(query1);
                }
            }
            DataUtilities.UpdateNorm(updateTdvt.ToString());
            DataUtilities.UpdateNorm(updateProvince.ToString());
        }

        #endregion
    }
}